package com.quectel.business.common.parking;

import com.quectel.base.tuple.Tuple3;
import com.quectel.base.tuple.Tuples;
import com.quectel.constant.core.PreWarnConstants;
import com.quectel.core.module.prewarning.dto.PreWarningConfigDto;
import com.quectel.core.module.prewarning.service.PreWarningConfigService;
import com.quectel.util.redis.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.Objects;
import java.util.function.Function;

/**
 * 在这里编写说明
 *
 * @author: ryan
 * @email: ryan.ran@quectel.com
 * @date: 2023-06-02 15:50:00
 */
@Component
@Slf4j
public class CarAccessLimitBusiness {

    /**
     * 车辆频繁出入set健名生成function
     * 小区id+车牌颜色+车牌号 -> setKeyName
     */
    public static final Function<Tuple3<Long, Byte, String>, String> CAR_ACCESS_SET_KEY_GEN_FUNC = t -> String.format("CAR_ACCESS_SET:%s_%s_%s", t.getT1(), t.getT2(), t.getT3());

    @DubboReference
    private PreWarningConfigService preWarningConfigService;

    public boolean isExceedingLimit(Long villageId, Byte licenseColor, String license) {
        PreWarningConfigDto preWarningConfigDto = preWarningConfigService.selectOne(villageId, PreWarnConstants.AlarmTypeEnum.CAR_RECORD_TOO_MANY.getType());
        if (Objects.isNull(preWarningConfigDto)) {
            log.warn("Pre warning config is null, unable to determine if the limit has been exceeded.");
            return false;
        }

        Tuple3<Long, Byte, String> of = Tuples.of(villageId, licenseColor, license);
        Long slideWindowCount = RedisUtils.getDefaultClient().getSlideWindowCount(CAR_ACCESS_SET_KEY_GEN_FUNC.apply(of)
                , Duration.ofMinutes(preWarningConfigDto.getRuleTime()));
        return slideWindowCount > preWarningConfigDto.getRuleNumber();
    }

    public boolean addItemToWindow(Long villageId, Byte licenseColor, String license) {
        PreWarningConfigDto preWarningConfigDto = preWarningConfigService.selectOne(villageId, PreWarnConstants.AlarmTypeEnum.CAR_RECORD_TOO_MANY.getType());
        if (Objects.isNull(preWarningConfigDto)) {
            log.warn("Pre warning config is null, unable to determine if the limit has been exceeded.");
            return false;
        }

        Tuple3<Long, Byte, String> of = Tuples.of(villageId, licenseColor, license);
        Long slideWindowCount = RedisUtils.getDefaultClient().addItemToSlideWindow(CAR_ACCESS_SET_KEY_GEN_FUNC.apply(of)
                , Duration.ofMinutes(preWarningConfigDto.getRuleTime()));
        return slideWindowCount > preWarningConfigDto.getRuleNumber();
    }

    public Long getItems(Long villageId, Byte licenseColor, String license) {
        PreWarningConfigDto preWarningConfigDto = preWarningConfigService.selectOne(villageId, PreWarnConstants.AlarmTypeEnum.CAR_RECORD_TOO_MANY.getType());
        if (Objects.isNull(preWarningConfigDto)) {
            log.warn("Pre warning config is null, unable to determine if the limit has been exceeded.");
            return null;
        }

        Tuple3<Long, Byte, String> of = Tuples.of(villageId, licenseColor, license);
        return RedisUtils.getDefaultClient().getSlideWindowCount(CAR_ACCESS_SET_KEY_GEN_FUNC.apply(of)
                , Duration.ofMinutes(preWarningConfigDto.getRuleTime()));
    }
}
